﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Threading;
using LinFu.AOP.Interfaces;

namespace BrainTechLLC
{
	public class RetryMethodReplacement : BaseMethodReplacementProvider, IMethodReplacement
	{
		public override bool ShouldReplace(IInvocationContext context)
		{
			RetryAttribute[] attrs = context.TargetMethod.ReadAttribute<RetryAttribute>();
			return (attrs != null && attrs.Length > 0);
		}

		protected override IMethodReplacement GetReplacement(IInvocationContext context)
		{
			return this;
		}

		public override object Invoke(IInvocationContext context)
		{
			RetryAttribute[] attrs = context.TargetMethod.ReadAttribute<RetryAttribute>();

			if (attrs == null || attrs.Length == 0)
				return context.TargetMethod.Invoke(context.Target, context.Arguments);

			for (int n = 0; n < attrs.Length; n++)
			{
				RetryAttribute attr = attrs[n];
				int tries = 0;
				while (tries < attr.RetryTimes)
				{
					try
					{
						return context.TargetMethod.Invoke(context.Target, context.Arguments);
					}
					catch
					{
						tries++;

						if (tries > attr.RetryTimes)
							throw;

						if (attr.SleepBetweenRetryMS >= 0)
							Thread.Sleep(attr.SleepBetweenRetryMS);
					}
				}
			}

			return null;
		}
	}
}

